package com.harmony.pilot.agent.tools;

import com.harmony.pilot.agent.model.ConversationContext;
import com.harmony.pilot.agent.model.Intent;
import com.harmony.pilot.agent.model.ToolRequest;
import com.harmony.pilot.agent.model.ToolResult;
import com.harmony.pilot.agent.service.LLMServiceClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.*;

/**
 * GN依赖检查和修复工具
 * 自动检测跨模块调用并建议GN依赖
 */
@Component
@Slf4j
public class GnDependencyTool implements AgentTool {
    
    private final LLMServiceClient llmServiceClient;
    private final RestTemplate restTemplate;
    
    @Value("${service.build.url:http://localhost:8086}")
    private String buildServiceUrl;
    
    @Value("${service.data.url:http://localhost:8085}")
    private String dataServiceUrl;
    
    public GnDependencyTool(LLMServiceClient llmServiceClient, 
                           @Autowired(required = false) RestTemplate restTemplate) {
        this.llmServiceClient = llmServiceClient;
        this.restTemplate = restTemplate != null ? restTemplate : new RestTemplate();
    }
    
    @Override
    public String getName() {
        return "gn_dependency";
    }
    
    @Override
    public String getDescription() {
        return "检查和修复GN依赖，自动检测跨模块调用并建议缺失的依赖";
    }
    
    @Override
    public String getParametersSchema() {
        return """
            {
              "type": "object",
              "properties": {
                "filePath": {
                  "type": "string",
                  "description": "要检查的C++源文件路径"
                },
                "gnFilePath": {
                  "type": "string",
                  "description": "对应的BUILD.gn文件路径（可选，会自动查找）"
                },
                "autoFix": {
                  "type": "boolean",
                  "description": "是否自动修复（添加缺失的依赖）"
                }
              },
              "required": ["filePath"]
            }
            """;
    }
    
    @Override
    public boolean canHandle(Intent intent, ConversationContext context) {
        String userMessage = context.getUserMessage();
        if (userMessage == null) {
            return false;
        }
        
        String lowerMessage = userMessage.toLowerCase();
        return lowerMessage.contains("gn依赖") ||
               lowerMessage.contains("gn dependency") ||
               lowerMessage.contains("检查依赖") ||
               lowerMessage.contains("缺失依赖") ||
               (lowerMessage.contains("依赖") && lowerMessage.contains("检查"));
    }
    
    @Override
    public double getRelevanceScore(Intent intent, ConversationContext context) {
        if (canHandle(intent, context)) {
            return 0.9;
        }
        return 0.0;
    }
    
    @Override
    public ToolResult execute(ToolRequest request) {
        Map<String, Object> params = request.getParameters();
        if (params == null) {
            params = new HashMap<>();
        }
        
        String filePath = (String) params.get("filePath");
        String gnFilePath = (String) params.get("gnFilePath");
        boolean autoFix = params.getOrDefault("autoFix", false).equals(true);
        
        if (filePath == null || filePath.isEmpty()) {
            filePath = request.getContext().getCurrentFile();
        }
        
        if (filePath == null || filePath.isEmpty()) {
            return ToolResult.error("未指定要检查的文件路径");
        }
        
        try {
            // 1. 分析跨模块调用
            List<CrossModuleCall> crossModuleCalls = analyzeCrossModuleCalls(filePath);
            
            // 2. 提取GN依赖建议
            Set<String> requiredDeps = new HashSet<>();
            for (CrossModuleCall call : crossModuleCalls) {
                if (call.getGnDepPath() != null && !call.getGnDepPath().isEmpty()) {
                    requiredDeps.add(call.getGnDepPath());
                }
            }
            
            // 3. 如果提供了GN文件路径，检查当前依赖
            List<String> missingDeps = new ArrayList<>();
            List<String> currentDeps = new ArrayList<>();
            
            if (gnFilePath != null && !gnFilePath.isEmpty()) {
                Map<String, Object> gnInfo = getGnDependencies(gnFilePath);
                if (gnInfo != null && gnInfo.containsKey("deps")) {
                    @SuppressWarnings("unchecked")
                    List<String> deps = (List<String>) gnInfo.get("deps");
                    currentDeps = deps;
                    
                    // 找出缺失的依赖
                    for (String requiredDep : requiredDeps) {
                        if (!currentDeps.contains(requiredDep)) {
                            missingDeps.add(requiredDep);
                        }
                    }
                }
            }
            
            // 4. 构建响应
            Map<String, Object> data = new HashMap<>();
            data.put("filePath", filePath);
            data.put("gnFilePath", gnFilePath);
            data.put("crossModuleCalls", crossModuleCalls);
            data.put("requiredDeps", new ArrayList<>(requiredDeps));
            data.put("currentDeps", currentDeps);
            data.put("missingDeps", missingDeps);
            
            StringBuilder message = new StringBuilder();
            message.append("📦 GN依赖检查结果\n\n");
            message.append("文件：").append(filePath).append("\n\n");
            
            if (crossModuleCalls.isEmpty()) {
                message.append("✅ 未发现跨模块调用\n");
            } else {
                message.append("🔍 发现 ").append(crossModuleCalls.size()).append(" 个跨模块调用：\n\n");
                for (CrossModuleCall call : crossModuleCalls) {
                    message.append("- 调用：").append(call.getCalleeFunction())
                           .append(" (").append(call.getCalleeModule()).append(")\n");
                    if (call.getGnDepPath() != null) {
                        message.append("  需要依赖：").append(call.getGnDepPath()).append("\n");
                    }
                    message.append("\n");
                }
            }
            
            if (!missingDeps.isEmpty()) {
                message.append("⚠️ 缺失的GN依赖（").append(missingDeps.size()).append("个）：\n");
                message.append("```gn\n");
                message.append("deps = [\n");
                for (String dep : missingDeps) {
                    message.append("  \"").append(dep).append("\",\n");
                }
                message.append("  # ... 其他依赖\n");
                message.append("]\n");
                message.append("```\n");
                
                if (autoFix && gnFilePath != null && !gnFilePath.isEmpty()) {
                    // TODO: 调用Build Service自动添加依赖
                    message.append("\n💡 提示：可以自动修复依赖（需要确认）\n");
                }
            } else if (!requiredDeps.isEmpty()) {
                message.append("✅ 所有依赖已正确配置\n");
            }
            
            return ToolResult.success(message.toString(), data);
            
        } catch (Exception e) {
            log.error("Failed to check GN dependencies", e);
            return ToolResult.error("检查GN依赖失败: " + e.getMessage());
        }
    }
    
    /**
     * 分析跨模块调用
     */
    private List<CrossModuleCall> analyzeCrossModuleCalls(String filePath) {
        try {
            Map<String, Object> request = new HashMap<>();
            request.put("filePath", filePath);
            
            Map<String, Object> response = restTemplate.postForObject(
                dataServiceUrl + "/data/openharmony/component/cross-module-calls",
                request,
                Map.class
            );
            
            if (response != null && "200".equals(String.valueOf(response.get("code")))) {
                @SuppressWarnings("unchecked")
                List<Map<String, Object>> callsData = (List<Map<String, Object>>) response.get("data");
                List<CrossModuleCall> calls = new ArrayList<>();
                
                if (callsData != null) {
                    for (Map<String, Object> callData : callsData) {
                        CrossModuleCall call = new CrossModuleCall();
                        call.setCallerFile((String) callData.get("callerFile"));
                        call.setCallerModule((String) callData.get("callerModule"));
                        call.setCalleeFile((String) callData.get("calleeFile"));
                        call.setCalleeModule((String) callData.get("calleeModule"));
                        call.setCalleeFunction((String) callData.get("calleeFunction"));
                        call.setCalleeQualifiedName((String) callData.get("calleeQualifiedName"));
                        call.setGnDepPath((String) callData.get("gnDepPath"));
                        calls.add(call);
                    }
                }
                
                return calls;
            }
        } catch (Exception e) {
            log.error("Failed to analyze cross-module calls", e);
        }
        
        return new ArrayList<>();
    }
    
    /**
     * 获取GN文件的依赖
     */
    private Map<String, Object> getGnDependencies(String gnFilePath) {
        try {
            Map<String, Object> response = restTemplate.getForObject(
                buildServiceUrl + "/build/gn/parse?filePath=" + gnFilePath,
                Map.class
            );
            
            if (response != null && "200".equals(String.valueOf(response.get("code")))) {
                @SuppressWarnings("unchecked")
                Map<String, Object> data = (Map<String, Object>) response.get("data");
                return data;
            }
        } catch (Exception e) {
            log.error("Failed to get GN dependencies", e);
        }
        
        return null;
    }
    
    private static class CrossModuleCall {
        private String callerFile;
        private String callerModule;
        private String calleeFile;
        private String calleeModule;
        private String calleeFunction;
        private String calleeQualifiedName;
        private String gnDepPath;
        
        // Getters and Setters
        public String getCallerFile() { return callerFile; }
        public void setCallerFile(String callerFile) { this.callerFile = callerFile; }
        
        public String getCallerModule() { return callerModule; }
        public void setCallerModule(String callerModule) { this.callerModule = callerModule; }
        
        public String getCalleeFile() { return calleeFile; }
        public void setCalleeFile(String calleeFile) { this.calleeFile = calleeFile; }
        
        public String getCalleeModule() { return calleeModule; }
        public void setCalleeModule(String calleeModule) { this.calleeModule = calleeModule; }
        
        public String getCalleeFunction() { return calleeFunction; }
        public void setCalleeFunction(String calleeFunction) { this.calleeFunction = calleeFunction; }
        
        public String getCalleeQualifiedName() { return calleeQualifiedName; }
        public void setCalleeQualifiedName(String calleeQualifiedName) { this.calleeQualifiedName = calleeQualifiedName; }
        
        public String getGnDepPath() { return gnDepPath; }
        public void setGnDepPath(String gnDepPath) { this.gnDepPath = gnDepPath; }
    }
}

